import { _decorator, Component, instantiate, Node, Prefab } from 'cc';
import { Unit } from '../Unit';
import { Global, UnitType } from '../../Util/Global';
import PoolManager from '../../Ctrl/PoolManager';
const { ccclass, property } = _decorator;

export enum SpawnEvent {
    START,
    SPAWNING,
    END
}

export interface ISpawnerEventCall {
    /**孵化事件回调 返回false会阻断*/
    SpawnEventCallback: ((unit: Unit, event: SpawnEvent) => boolean);
}

/**孵化组件 */
@ccclass('SpawnerCom')
export class SpawnerCom extends Component {
    //预制体
    protected spawnPrefabs: Map<UnitType, Map<string, Prefab>> = new Map();
    /**所有的生产车间 */
    protected workshop: Array<Workshop> = new Array();

    get WorkQueue() {
        return this.workshop;
    }

    /**孵化事件回调 */
    public onSpawnEventCallback(key: string, target: ISpawnerEventCall) {
        let pool = this._onSpawnEventCall.get(key) || [];
        pool.push(target);
        this._onSpawnEventCall.set(key, pool);
    }

    /**孵化事件回调 */
    public offSpawnEventCallback(key: string, target: ISpawnerEventCall) {
        let pool = this._onSpawnEventCall.get(key) || [];
        let index = pool.indexOf(target);
        if (index !== -1) {
            pool.splice(index, 1);
            this._onSpawnEventCall.set(key, pool);
        }
    }

    /**单位生产完成回调 */
    protected _onSpawnEventCall: Map<string, ISpawnerEventCall[]> = new Map();

    getWorkshop(unitType: UnitType | Prefab | string): Workshop {
        let targetWork = null;
        this.workshop.forEach(work => {
            if (typeof unitType === 'number') {
                if (work.productType == unitType) {
                    targetWork = work;
                }
            }
            else if (typeof unitType === 'string') {
                if (work.prefeb.name == unitType) {
                    targetWork = work;
                }
            }
            else if (work.prefeb == unitType) {
                targetWork = work;
            }
        });

        return targetWork;
    }

    protected spawnUnit: Array<Unit> = [];

    FilterSpawnedChildren(call: (unit: Unit) => boolean) {
        for (let i = 0; i < this.spawnUnit.length; i++) {
            let unit = this.spawnUnit[i];
            if (call(unit)) {
                return unit;
            }
        }

        return null;
    }

    /**默认父单位 */
    public unit: Unit = null;
    public childrenParent: Node = null;

    /**正在生产的产品数量 */
    protected _spawningCount = 0;
    get spawningCount() {
        return this._spawningCount;
    }

    start() {
        this.unit = this.getComponent(Unit);
    }

    update(deltaTime: number) {
        if (Global.gameManager.pause) {
            return;
        }
        this.Spawning(deltaTime);
    }

    protected onDisable(): void {
        this.spawnUnit = [];
        // this._onSpawnEventCall.clear();
        this._spawningCount = 0;
        this.ClearWorkShop();
    }

    /**生产 */
    Spawning(dt) {
        if (this.spawnUnit && this._spawningCount > 0) {
            let remainNum = 0;
            for (let i = 0; i < this.workshop.length; i++) {
                let has = this.workshop[i].Producing(dt);
                if (has) {

                    // let node = instantiate(this.spawnPrefabs.get(this.workshop[i].productType));
                    // let p = this.spawnPrefabs.get(this.workshop[i].productType);
                    let p = this.workshop[i].prefeb;
                    let node = PoolManager.getNode(p);
                    node.setParent(this.childrenParent || this.node.parent);
                    node.position = this.node.position;
                    let unit = node.getComponent(Unit);
                    // unit.prefabName = p.name;
                    unit.parentUnit = this.unit;

                    this.spawnUnit.push(unit);
                    this._onSpawnEventCall.forEach(pool => {
                        for (let i = 0; i < pool.length; i++) {
                            let call = pool[i];
                            if (!call.SpawnEventCallback(unit, SpawnEvent.SPAWNING)) {
                                break;
                            }
                        }
                    });
                }

                remainNum += this.workshop[i].productNum;
            }

            this._spawningCount = remainNum;

            if (this._spawningCount <= 0) {
                this._onSpawnEventCall.forEach(pool => {
                    for (let i = 0; i < pool.length; i++) {
                        let call = pool[i];
                        if (!call.SpawnEventCallback(null, SpawnEvent.END)) {
                            break;
                        }
                    }
                });
            }
        }

    }

    getSpawnChildren(out?: Array<Unit>): Array<Unit> {

        if (out) {
            this.spawnUnit = out;
        }
        else {
            out = [];
        }

        for (let i = 0; i < this.spawnUnit.length; i++) {
            if (this.spawnUnit[i] && this.spawnUnit[i].isValid) {
            }
            else {
                this.spawnUnit.splice(i, 1);
                i--;
            }
        }

        return this.spawnUnit;
    }

    /**添加产品预制体 */
    AddProduct(prefab: Prefab) {
        if (!prefab) return;
        let unit = prefab.data.getComponent(Unit);
        let has = false;
        if (unit) {
            let type_arr = this.spawnPrefabs.get(unit.unitType) || new Map<string, Prefab>();
            has = type_arr.has(prefab.name);
            type_arr.set(prefab.name, prefab);
            this.spawnPrefabs.set(unit.unitType, type_arr);
        }
        else {
            //设置默认单位
            let type_arr = this.spawnPrefabs.get(UnitType.Base) || new Map<string, Prefab>();
            has = type_arr.has(prefab.name);
            type_arr.set(prefab.name, prefab);
            this.spawnPrefabs.set(UnitType.Base, type_arr);
        }

        if (has) {
            return;
        }
        let work = new Workshop();
        work.spawner = this;
        work.productType = unit.unitType;
        work.prefeb = prefab;
        work.interval = unit.spawn_time;

        this.workshop.push(work);
    }

    /**取消生产 */
    ClearWorkShop(type: UnitType = UnitType.Base, reset = false) {
        if (reset) {
            this.workshop = [];
            return;
        }
        if (type == UnitType.Base) {
            for (let i = 0; i < this.workshop.length; i++) {
                let work = this.workshop[i];
                work.productNum = 0;
                work.time = 0;
            }
        }
        else {
            this.workshop.forEach(work => { if (work.productType == type) { work.productNum = 0 } });
        }
    }

    /**获取所有空闲生产车间 */
    GetIdleWorkShops(): Workshop[] {
        let works = [];
        for (let i = 0; i < this.workshop.length; i++) {
            let work = this.workshop[i];
            if (work.productNum <= 0) {
                works.push(work);
            }
        }

        return works;
    }

    /**获取所有在生产的单位 制造完后总电力负载 */
    GetElectricConsume_afterCompletingProduction() {
        let sum = 0;
        if (this.workshop) {
            for (let i = 0; i < this.workshop.length; i++) {
                let work = this.workshop[i];
                sum += work.prefeb.data.getComponent(Unit).power_cost * work.productNum;
            }
        }

        return sum;
    }

    /**
     * 启动所有空闲的生产车间
     * @param workNum 增加生产数量
     * @returns 启动数量
     */
    StartIdleWorkShop(workNum: number = 1): number {
        let startNum = 0;
        for (let i = 0; i < this.workshop.length; i++) {
            let work = this.workshop[i];
            if (work.productNum <= 0) {
                // work.productNum = workNum;
                // this._spawningCount += workNum;
                this.AddProductNum(work.productType, workNum);
                startNum++;
            }
        }

        return startNum;
    }

    /**增加该种类的单位待生产的数量 */
    AddProductNum(type: UnitType | Prefab | string, num: number) {
        let work = this.getWorkshop(type);
        if (work) {
            if (num > 0 && this._spawningCount <= 0) {
                this._onSpawnEventCall.forEach(pool => {
                    for (let i = 0; i < pool.length; i++) {
                        let call = pool[i];
                        if (!call.SpawnEventCallback(null, SpawnEvent.START)) {
                            break;
                        }
                    }
                });
            }
            work.productNum += num;
            this._spawningCount += num;
        }
    }

    Reset(): void {
        this.ClearWorkShop(0, true);
        this.spawnPrefabs.clear();
        this._onSpawnEventCall = new Map();
    }

    DestroyAllChildren(reason?: string) {
        if (this.spawnUnit) {
            this.spawnUnit.forEach(v => v.DestroySelf(reason));
        }
    }
}

/**生产车间 */
export class Workshop {
    /**产品类型 */
    public productType: UnitType = UnitType.Base;
    /**所属的孵化模块 */
    public spawner: SpawnerCom = null;

    /**待生产数量 */
    public productNum: number = 0;

    public time: number = 0;
    //冷却时间
    public interval: number = 0;

    public prefeb: Prefab = null;

    /**
     * 生产
     * @param dt 
     * @returns 是否可以生产
     */
    Producing(dt): boolean {
        if (this.productNum > 0) {
            this.time += dt;
            if (this.time > this.interval) {//冷却，，，
                this.time = 0;
                this.productNum--;
                return true;
            }
        }

        return false;
    }

    /**增加该种类的单位待生产的数量 */
    AddProductNum(num: number) {
        if (this.spawner.node && this.spawner.node.isValid) {

            this.spawner.AddProductNum(this.productType, num);
        }
    }
}


